-- SPDX-License-Identifier: MIT
-- Author: Coalball chen <805755827@qq.com>
local time = require 'eco.time'

-- 消息队列结构
local msg_queue = {}
msg_queue.__index = msg_queue

-- 初始化消息队列
function msg_queue:new(max_size)
    local self = setmetatable({
        max_size = max_size or 100,
        queue = {},                   -- 存储消息的队列
        lock = { held = false },      -- 互斥锁
    }, msg_queue)

    return self
end

-- 获取锁（忙等待）
function msg_queue:acquire_lock()
    while self.lock.held do
        time.sleep(0.001)  -- 让出 CPU 时间片
    end
    self.lock.held = true
end

-- 释放锁
function msg_queue:release_lock()
    self.lock.held = false
end

local function _send(self, msg, timeout, insert_pos)
    local start_time = os.time()
    while true do
        self:acquire_lock()
        if #self.queue < self.max_size then
            if insert_pos then
                table.insert(self.queue, insert_pos, msg)
            else
                table.insert(self.queue, msg)
            end
            self:release_lock()
            return true
        else
            self:release_lock()
            local elapsed = os.time() - start_time
            if timeout and elapsed >= timeout then
                return false, "timeout"
            end
            time.sleep(math.min(0.001, timeout - elapsed))  -- 最多等待 1ms
        end
    end
end

-- 发送普通消息（插入队列尾部）
function msg_queue:send(msg, timeout)
    return _send(self, msg, timeout)
end

-- 发送紧急消息（插入队列头部）
function msg_queue:send_urgent(msg, timeout)
    return _send(self, msg, timeout, 1)
end

-- 接收消息（带超时）
function msg_queue:recv(timeout)
    local start_time = os.time()
    while true do
        self:acquire_lock()
        if #self.queue > 0 then
            local msg = table.remove(self.queue, 1)
            self:release_lock()
            return msg
        else
            self:release_lock()
            local elapsed = os.time() - start_time
            if timeout and elapsed >= timeout then
                return nil, "timeout"
            end
            time.sleep(math.min(0.1, timeout - elapsed))  -- 最多等待 100ms
        end
    end
end

return msg_queue